package com.oazon.moco.playlist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.util.Log;

import com.oazon.common.Assert;
import com.oazon.common.Logger;
import com.oazon.common.Settings;
import com.oazon.common.TaskHelper;
import com.oazon.moco.bean.Metadata;
import com.oazon.moco.playlist.bean.PlayListCurrentMode;
import com.oazon.moco.playlist.db.ResourceDao;
import com.oazon.moco.playlist.http.ParamsAysncListener;
import com.oazon.moco.playlist.http.RequestMediaManage;
import com.oazon.sonos.bean.GetMetadata;

public class PlayListManage {

	private static final String TAG = "PlayListManage";
	public static final String PLAY_MODE = "play_mode";
	public static final String PLAY_MODE_RADIO = "radio";
	public static final String PLAY_MODE_QUEUE = "queue";
	private int smartRadioOnceItem = 5;
	private static Context context;
	private static PlayListManage playListManage = null;
	private ResourceDao resourceDao;
	private GetMetadata getMetadata;
	private PlayListCurrentMode saveCurrentMode = PlayListCurrentMode.QUEUE;
	private PagerAdapter adapter = null;
	private PlayList<Metadata> playList = null;
	
	public static void init(Context context) {
		PlayListManage.context = context;
	}

	public void registViewPagerAdapter(PagerAdapter adapter) {
		this.adapter = adapter;
	}

	private void notifiDateChange() {
		if (adapter != null) {
			adapter.notifyDataSetChanged();
		}
	}

	/**
	 * 初始化的时候会去加载本地播放列表
	 */
	private PlayListManage() {
		resourceDao = new ResourceDao(context);
		playList = MediaPlayList.getInstance(context);
		autoLoadImage();
	}

	public GetMetadata getGetMetadata() {
		return getMetadata;
	}

	public void setGetMetadata(GetMetadata getMetadata) {
		this.getMetadata = getMetadata;
	}

	public int getSmartRadioOnceItem() {
		return smartRadioOnceItem;
	}

	public void setSmartRadioOnceItem(int smartRadioOnceItem) {
		this.smartRadioOnceItem = smartRadioOnceItem;
	}

	public synchronized int calFetchSize() {
		Assert.notNull(playList);
		int calFatchSize = 0;

		if (saveCurrentMode == PlayListCurrentMode.SMART_RADIO) {
			calFatchSize = playList.getHistorySize();
			if (playList instanceof RadioPlayList) {
				int index = ((RadioPlayList) playList).calLastNoRecommanIndex();
				if (index >= 0) {
					calFatchSize = playList.getHistorySize() - index + 1;
				}
			}
		}

		if (calFatchSize < 0) {
			calFatchSize = 0;
		}

		return calFatchSize;
	}

	public synchronized boolean toSmartRadio(GetMetadata getMetadata) {
		Logger.d(TAG, "toSmartRadio  === ");
		Settings.getInstance(context).set(PLAY_MODE, PLAY_MODE_RADIO);
		playList = RadioPlayList.getInstance(context);
		if (getMetadata != null) {
			this.getMetadata = getMetadata;
		}
		saveCurrentMode = PlayListCurrentMode.SMART_RADIO;
		return true;
	}

	public synchronized boolean toQueue() {
		Logger.d(TAG, "toQueue  === ");
		playList = MediaPlayList.getInstance(context);
		Settings.getInstance(context).set(PLAY_MODE, PLAY_MODE_QUEUE);
		if (saveCurrentMode == PlayListCurrentMode.QUEUE) {
			return true;
		}
		try {
			getMetadata = null;
			saveCurrentMode = PlayListCurrentMode.QUEUE;
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public PlayListCurrentMode getSaveCurrentMode() {
		return saveCurrentMode;
	}

	public void setSaveCurrentMode(PlayListCurrentMode saveCurrentMode) {
		this.saveCurrentMode = saveCurrentMode;
	}

	/**
	 * 移除队首的一首媒体.同时删除sd卡中保存的图片
	 */
	public synchronized boolean removeFirst() {
		Assert.notNull(playList);
		try {
			if (playList.size() > 0) {
				Metadata data = playList.remove(0);
				if (getReadIndex() == 0) {
					setReadIndex(0);
				} else {
					setReadIndex(getReadIndex() - 1);
				}

				if (data != null) {
					resourceDao.deleteBitmapSD(data.getItemID());
					return true;
				}

			} else {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 移除index位置的媒体 同时删除sd卡中保存的图片
	 * 
	 * @param index
	 */
	public synchronized boolean remove(int index) {
		Assert.notNull(playList);
		try {
			if (index < 0 || index >= playList.size()) {
				return false;
			}
			Metadata metadata = playList.get(index);
			playList.remove(index);
			if (index < getReadIndex()) {
				playList.setReadIndex(getReadIndex() - 1);
			}
			resourceDao.deleteBitmapSD(metadata.getItemID());
			return true;
		} catch (Exception e) {
			return false;
		}

	}

	/**
	 * 移除所有index的媒体 同时删除sd卡中保存的图片
	 * 
	 * @param index
	 */
	public synchronized boolean removeAll(int... index) {
		ArrayList<Metadata> Metadatas = new ArrayList<Metadata>();
		int[] indexs = index;
		Assert.notNull(playList);
		try {
			for (int i = 0; i < indexs.length; i++) {
				Metadatas.add(playList.get(indexs[i]));
				resourceDao.deleteBitmapSD(playList.remove(indexs[i])
						.getItemID());
			}
			return true;
		} catch (Exception e) {
			// 删除失败回滚状态
			for (int i = 0; i < Metadatas.size(); i++) {
				playList.add(indexs[i], Metadatas.get(i));
			}
			return false;
		}

	}

	/**
	 * 从index位置开始替换List.size()个媒体
	 * 
	 * @param index
	 * @param os
	 */
	public synchronized boolean replaceAll(int index, List<Metadata> os) {
		Assert.notNull(playList);
		// 队列超过上限不允许添加
		if ((index + os.size()) > playList.getMaxSize()) {
			return false;
		}
		for (int i = 0; i < os.size(); i++) {
			playList.remove(index + i);
			playList.setReadIndex(index);
			Logger.d(TAG, "replaceAll==" + getReadIndex());
		}
		if (playList.addAll(index, os)) {
			return true;
		} else {
			return false;
		}

	}

	public synchronized boolean update(Metadata Metadata) {
		Assert.notNull(playList);
		try {
			int index = getIndex(Metadata.getItemID());
			playList.remove(index);
			playList.add(index, Metadata);
			notifiDateChange();
			return true;
		} catch (Exception e) {
			return false;
		}

	}

	/**
	 * 在队尾添加一个媒体
	 * 
	 * @param o
	 */
	public synchronized boolean add(Metadata o) {
		Assert.notNull(playList);
		Assert.notNull(o);
		if (playList.add(o)) {
			if (!o.isAutoAdd()) {
				playList.setWriteIndex(playList.indexOf(o));
			}
			if (playList.size() >= playList.getMaxSize()) {
				removeFirst();
			}
			return true;
		} else {
			return false;
		}

	}

	/**
	 * 在队尾添加一组媒体
	 * 
	 * @param os
	 */
	public synchronized boolean addAll(List<Metadata> os) {
		// 队列超过上限不允许添加
		Assert.notNull(playList);
		for (Metadata Metadata : os) {
			if (!Metadata.isAutoAdd()) {
				playList.setWriteIndex(playList.indexOf(Metadata));
			}
		}

		if (playList.addAll(os)) {
			if (playList.size() >= playList.getMaxSize()) {
				for (int i = 0; i < playList.size() - playList.getMaxSize(); i++) {
					removeFirst();
				}
			}
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 在index位置插入一个元素
	 * 
	 * @param o
	 * @param index
	 */
	public synchronized boolean add(Metadata o, int index) {
		Assert.notNull(playList);
		try {
			playList.add(index, o);

			if (!o.isAutoAdd()) {
				playList.setWriteIndex(playList.indexOf(o));
			}
			if (playList.size() > playList.getMaxSize()) {
				removeFirst();
			}

			return true;
		} catch (Exception e) {
			return false;
		}

	}

	/**
	 * 在index的位置插入一组媒体
	 * 
	 * @param os
	 * @param index
	 */
	public synchronized boolean addAll(List<Metadata> os, int index) {
		int i = 0;
		Assert.notNull(playList);
		try {
			playList.addAll(index, os);
			if (playList.size() >= playList.getMaxSize()) {
				for (int j = 0; j < playList.size() - playList.getMaxSize(); j++) {
					removeFirst();
				}
			}
			return true;
		} catch (Exception e) {
			// 添加失败回滚状态 ???什么用？
			for (int j = 0; j < i; j++) {
				remove(index + j);
				Logger.i(TAG, "添加列表失败");
			}
			return false;
		}

	}

	/**
	 * 返回当前播放的媒体
	 * 
	 * @return
	 */
	public synchronized Metadata getCurrentMedia() {
		Assert.notNull(playList);
		Logger.i(TAG, "====size==" + playList.size() + "|||readIndex=="
				+ getReadIndex());


		for (int i = 0; i < playList.size(); i++) {
			Logger.i(TAG, "=title=" + playList.get(i).getTitle());
		}
		if (playList.size() == 0) {// 1
			return null;
		}
		return playList.get(getReadIndex());
	}

	public synchronized int getCurrentIndex() {
		Assert.notNull(playList);
		return getReadIndex();
	}

	Thread autoLoadImage = null;
	boolean isRunning = false;

	public void autoLoadImage() {
		isRunning = true;
		TaskHelper.exec(new AutoLoadRunnable());
	}

	public void stopAutoLoadImage() {
		isRunning = false;
	}

	/**
	 * 得到index位置的媒体
	 * 
	 * @param index
	 * @return
	 */
	public synchronized Metadata getMedia(int index) {
		Assert.notNull(playList);
		if (index < 0) {
			return null;
		}
		if (playList.size() <= index) {
			return null;
		}
		return playList.get(index);
	}

	/**
	 * 得到当前id的歌曲所在的位置
	 * 
	 * @param id
	 * @return -1为没有找到
	 */
	public synchronized int getIndex(String id) {
		if (id == null) {
			return -1;
		}
		int index = -1;
		for (int i = 0; i < playList.size(); i++) {

			if (id.equals(playList.get(i).getItemID())) {
				index = i;
			}
		}
		return index;
	}

	public synchronized Metadata getIndexMetadata(String id) {
		if (id == null) {
			return null;
		}

		for (int i = 0; i < playList.size(); i++) {

			if (id.equals(playList.get(i).getItemID())) {

				return playList.get(i);
			}
		}
		return null;

	}

	public synchronized Metadata getMetadata(String id) {
		if (id == null || playList.getPlayList() == null) {
			return null;
		}

		for (Metadata tempObj : playList.getPlayList()) {
			if (id.equals(tempObj.getItemID())) {
				return tempObj;
			}
		}
		return null;

	}

	/**
	 * 清空播放列表
	 */
	public synchronized void clearPlayList() {
		Assert.notNull(playList);
		playList.clear();
		playList.setReadIndex(0);
	}

	/**
	 * 播放index这首歌
	 * 
	 * @param index
	 * @return
	 */
	public synchronized Metadata getPlay(int index) {
		if (index < 0 || index >= playList.size()) {
			return null;
		}
		Metadata temp = null;
		setReadIndex(index);
		Logger.d(TAG, "getPlay==" + getReadIndex());
		temp = playList.get(index);
		if (getReadIndex() > getHistorySize()) {
			removeFirst();
			// TODO 去请求添加add();
		}
		Logger.d(TAG, "readIndex===" + getReadIndex());
		Logger.d(TAG, "writeIndex===" + playList.getWriteIndex());
		return temp;
	}

	public int size() {
		return playList.size();
	}

	public synchronized static PlayListManage getInstance() {
		if (playListManage == null) {
			playListManage = new PlayListManage();
		}

		return playListManage;
	}

	public int getHistorySize() {
		return playList.getHistorySize();
	}

	public void setHistorySize(int historySize) {
		playList.setHistorySize(historySize);
	}

	public int getBufferSize() {
		return playList.getBufferSize();
	}

	public void setBufferSize(int bufferSize) {
		playList.setBufferSize(bufferSize);
	}

	public int getDynamicSize() {
		return playList.getDynamicSize();
	}

	public void setDynamicSize(int dynamicSize) {
		playList.setDynamicSize(dynamicSize);
	}

	public int getMaxSize() {
		return playList.getMaxSize();
	}

	public void setMaxSize(int maxSize) {
		playList.setMaxSize(maxSize);
	}

	public int getWriteIndex() {
		return playList.getWriteIndex();
	}

	public void setWriteIndex(int writeIndex) {
		playList.setWriteIndex(writeIndex);
	}

	public int getReadIndex() {
		return playList.getReadIndex();
		
	}

	public boolean isFavorite(int index) {
		Assert.notNull(playList);
		if (index < 0 || playList.get(index) == null) {
			return false;
		}
		return playList.get(index).isFavorite();

	}

	private void setReadIndex(int readIndex) {
		if (readIndex >= playList.size()) {
			playList.setReadIndex(0);
		} else if (readIndex < 0) {
			playList.setReadIndex(playList.size() - 1);
		} else {
			playList.setReadIndex(readIndex);
		}
	}

	public synchronized void update() {
		if (playList instanceof RadioPlayList)
			((RadioPlayList) playList).update(getReadIndex());
	}

	public void dumpPlaylist() {
		if (playList instanceof MediaPlayList)
			((MediaPlayList) playList).dumpPlaylist();
		else if (playList instanceof RadioPlayList) {
			((RadioPlayList) playList).dumpPlaylist();
		}
	}

	public int calLastNoRecommanIndex() {
		if (playList instanceof RadioPlayList)
			return ((RadioPlayList) playList).calLastNoRecommanIndex();
		return -1;
	}

	public void clearNoRecommanSongs() {
		if (playList instanceof RadioPlayList)
			((RadioPlayList) playList).clearNoRecommanSongs();
	}

	public void syncDb() {
		if (playList instanceof MediaPlayList)
			((MediaPlayList) playList).syncDb();
	}

	private boolean isPauseAutoLoad = false;

	public void pauseAutoLoad() {
		isPauseAutoLoad = true;
	}

	public void reStartAutoLoad() {
		isPauseAutoLoad = false;
	}

	private class AutoLoadRunnable implements Runnable {

		@Override
		public void run() {

			int oldReadIndex = -1;

			while (isRunning) {

				if (oldReadIndex != getReadIndex() && !isPauseAutoLoad) {
					oldReadIndex = getReadIndex();
					int cacheSize = 4;
					if (cacheSize > size()) {
						cacheSize = size();
					}

					for (int i = 0; i < cacheSize; i++) {

						int index = getReadIndex() - cacheSize / 2 + i;

						if (index < 0) {
							index += size();
						}

						if ((size() - index) <= 0) {
							index = Math.abs(size() - index);
						}
						final int finalIndex = index;
						Metadata indexMetadata = getMedia(finalIndex);

						if (indexMetadata == null) {
							continue;
						}
						Logger.i("cache__", "index==" + finalIndex);

						String url = indexMetadata.getAlbumArtURI();

						Map<String, Object> params = new HashMap<String, Object>();
						params.put("url", url);
						RequestMediaManage.getInstance(context).requestBitmap(
								url, new ParamsAysncListener(params) {

									@Override
									public void onSuccess(Object o) {
									}

									@Override
									public void onError(String error) {
									}
								});
					}
				}

				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

		}
	}
}
